# Project Jocara

import pygame
from pygame.locals import *
from math import floor, ceil

import system
import menu

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((60,60)).convert_alpha()
        self.image.fill((0,)*4)
        pygame.draw.circle(self.image, pygame.Color('white'), (30,30), 30)
        self.rect = self.image.get_rect(center=(
                            system.screen.get_width()/2,
                            system.screen.get_height()/2))
        
def build_map():
    global local_map
    local_map = (1,1,1,1,1,1,1,1,1,
                 1,0,0,0,0,0,0,0,1,
                 1,0,1,1,0,0,0,0,1,
                 1,0,1,0,0,0,0,0,1,
                 1,0,0,0,0,0,0,0,1,
                 1,0,0,0,0,0,1,0,1,
                 1,0,0,0,0,1,1,0,1,
                 1,0,0,0,0,0,0,0,1,
                 1,1,1,1,1,1,1,1,1)
    
    ground = pygame.Surface((70*9,70*9))
    ground.fill((0,50,0))
    
    pos = [0,0]
    #t = 0
    for tile in local_map:
        if tile is 1:
            pygame.draw.rect(ground, pygame.Color('brown'), pygame.Rect(pos[0],pos[1],70,70))
        #ground.blit(system.font[1].render(str(t), True, pygame.Color('white')),pos)
        #t += 1
        pos[0] += 70
        if pos[0] >= ground.get_rect().width:
            pos[0] = 0
            pos[1] += 70
            
    return ground

def build_collision_map(pos_): # Obsolete
    pos = [0,0]
    col_map = []
    for tile in local_map:
        if tile is 1:
            col_map.append(pygame.Rect(pos[0]+pos_[0],pos[1]+pos_[1],70,70))
        pos[0] += 70
        if pos[0] >= 70*9:
            pos[0] = 0
            pos[1] += 70
    return tuple(col_map)

def accel_vectors(target, vec):
    acceleration = 0.5
    for a in (0,1):
        if vec[a] < target[a]:
            vec[a] += acceleration
        elif vec[a] > target[a]:
            vec[a] -= acceleration
    return [int(vec[0]),int(vec[1])]

def get_cell(pos):
    center_point = (system.screen.get_width()/2,
                    system.screen.get_height()/2)
    cell = [floor((center_point[a] - pos[a])/70) for a in (0,1)]
    #print(cell,int(cell[0]+cell[1]*9))
    if local_map[cell[0]+cell[1]*9] is 1:
        return True
    else:
        return False

def get_adjacent_cell(pos,dir_):
    point = ((system.screen.get_width()/2 - pos[0]) % 70,
            (system.screen.get_height()/2 - pos[1]) % 70)
    if dir_ is 0:
        dist = point[1]
        blocked = get_cell((pos[0],pos[1]+70))
    elif dir_ is 1:
        dist = 70 - point[0]
        blocked = get_cell((pos[0]-70,pos[1]))
    elif dir_ is 2:
        dist = 70 - point[1]
        blocked = get_cell((pos[0],pos[1]-70))
    elif dir_ is 3:
        dist = point[0]
        blocked = get_cell((pos[0]+70,pos[1]))
    #print(str(dist),str(dir_),str(blocked))1112
    return blocked, dist

def get_diag_cell(pos,dir_):
    point = ((system.screen.get_width()/2 - pos[0]) % 70,
            (system.screen.get_height()/2 - pos[1]) % 70)
    
    if dir_ is 0 and point[0] < 35 or dir_ is 3 and not point[1] > 35:
        blocked = get_cell((pos[0]+70,pos[1]+70))
    elif dir_ is 0 and not point[0] < 35 or dir_ is 1 and not point[1] > 35:
        blocked = get_cell((pos[0]-70,pos[1]+70))
    elif dir_ is 1 and point[1] > 35 or dir_ is 2 and not point[0] < 35:
        blocked = get_cell((pos[0]-70,pos[1]-70))
    elif dir_ is 2 and point[0] < 35 or dir_ is 3 and point[1] > 35:
        blocked = get_cell((pos[0]+70,pos[1]-70))
    
    if (dir_ is 0 or dir_ is 2) and point[0] < 35:
        dist = point[0]
    elif (dir_ is 0 or dir_ is 2) and not point[0] < 35:
        dist = 70 - point[0]
    elif (dir_ is 1 or dir_ is 3) and point[1] > 35:
        dist = 70 - point[1]
    elif (dir_ is 1 or dir_ is 3) and not point[1] > 35:
        dist = point[1]
    #print(str(dist),str(dir_),str(blocked))
    return blocked, dist

def calculate_collision(pos,vec):
    collided = [False, False]
    for i in (0,1):
        if int(vec[i]) is not 0:
            if vec[i] > 0:
                blocked, dist = get_adjacent_cell(pos,3-i*3)
            else:
                blocked, dist = get_adjacent_cell(pos,1+i)
            if blocked and dist - abs(vec[i]) < 30:
                vec[i] = 30 - dist if vec[i] < 0 else dist - 30
                collided[i] = True
                continue
            if vec[i] > 0:
                blocked, adist = get_diag_cell(pos,3-i*3)
            else:
                blocked, adist = get_diag_cell(pos,1+i)
            if blocked and adist < 30 and dist - abs(vec[i]) < 30:
                vec[i] = 30 - dist if vec[i] < 0 else dist - 30
                collided[i] = True
    return tuple(collided)

def test():
    # Background
    background = pygame.Surface(system.screen.get_size())
    background.fill((30,)*3)
    
    ground = build_map()
    g_pos = list(ground.get_rect(center=(
                            system.screen.get_width()/2,
                            system.screen.get_height()/2)).topleft)
    text = (menu.Text(system.font[1],'Esc to quit'),
            menu.Text(system.font[1],'WASD to move'))
    text[0].rect.topleft = (40,40)
    text[1].rect.topleft = (40,80)
    player = Player()
    temp = pygame.sprite.RenderPlain((player,)+text)
    vel_vector = [0,0]
    
    while True:
        system.clock.tick(60)

        for event in pygame.event.get():
            if event.type == QUIT:
                return 0
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                return 1
            elif event.type is MOUSEBUTTONUP:
                pass
            
        keys = pygame.key.get_pressed()
        g_pos_orig = tuple(g_pos)
        move_vector = [0,0]
        inc = 7
        
        if keys[K_a]:
            move_vector[0] = inc
        if keys[K_d]:
            move_vector[0] = -inc
        if keys[K_w]:
            move_vector[1] = inc
        if keys[K_s]:
            move_vector[1] = -inc
            
        # Prevent the speed hack
        if all(map(lambda a: a is not 0,move_vector)):
            move_vector = tuple(map(lambda a: int(a*0.707106781),move_vector))
            
        prod_vector = accel_vectors(move_vector, vel_vector)
        
        if any(map(lambda f: f is not 0,prod_vector)):
            collision = calculate_collision(g_pos,prod_vector)
            for a in (0,1):
                if collision[a]:
                    vel_vector[a] = 0

        g_pos = tuple(map(sum,zip(prod_vector,g_pos)))
                
        system.screen.blit(background, (0,0))
        system.screen.blit(ground,g_pos)
        
        temp.update()
        temp.draw(system.screen)
        pygame.display.flip()
        